package com.jtny.nytb.weather.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jtny.component.contants.GenericConstants;
import com.jtny.component.core.util.PageUtils;
import com.jtny.component.core.util.QueryWrapperUtils;
import com.jtny.component.entity.PageData;
import com.jtny.component.entity.PageParam;
import com.jtny.component.exception.ServiceException;
import com.jtny.component.util.BeanUtils;
import com.jtny.nytb.weather.dao.*;
import com.jtny.nytb.weather.entity.domain.*;
import com.jtny.nytb.weather.entity.dto.WeatherApiInfoDTO;
import com.jtny.nytb.weather.entity.dto.WeatherRequestDTO;
import com.jtny.nytb.weather.entity.dto.WeatherResponseDTO;
import com.jtny.nytb.weather.entity.vo.RequestParamInfoVO;
import com.jtny.nytb.weather.entity.vo.ResponseParamInfoVO;
import com.jtny.nytb.weather.entity.vo.WeatherApiInfoPageQueryParamVO;
import com.jtny.nytb.weather.entity.vo.WeatherApiInfoVO;
import com.jtny.nytb.weather.service.WeatherSourcesService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class WeatherSourcesServiceImpl implements WeatherSourcesService {

    @Resource
    private WeatherApiInfoDAO weatherApiInfoDAO;

    @Resource
    private WeatherRequestDAO weatherRequestDAO;

    @Resource
    private WeatherApiRequestRelationDAO weatherApiRequestRelationDAO;

    @Resource
    private WeatherResponseDAO weatherResponseDAO;

    @Resource
    private WeatherApiResponseRelationDAO weatherApiResponseRelationDAO;

    @Override
    public void saveApiInfo(WeatherApiInfoVO weatherApiInfoVO) {
        if (weatherApiInfoVO == null) {
            throw new ServiceException("传入参数为空");
        }
        // 请求方式以 / 分割
        List<String> requestTypeList = weatherApiInfoVO.getRequestType();
        String requestTypes = String.join("/", requestTypeList);
        // TODO 有无参数的限制条件
        WeatherApiInfoDO weatherApiInfoDO = new WeatherApiInfoDO();
        weatherApiInfoDO.setName(weatherApiInfoVO.getName());
        weatherApiInfoDO.setUrl(weatherApiInfoVO.getUrl());
        weatherApiInfoDO.setRequestType(requestTypes);
        weatherApiInfoDO.setIsFree(weatherApiInfoVO.getIsFree());
        weatherApiInfoDO.setFrequency(weatherApiInfoVO.getFrequency());
        weatherApiInfoDO.setCharge(weatherApiInfoVO.getCharge());
        weatherApiInfoDO.setApiKey(weatherApiInfoVO.getApiKey());
        weatherApiInfoDO.setApiType(weatherApiInfoVO.getApiType());

        weatherApiInfoDAO.insert(weatherApiInfoDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteApiInfo(Long id) {
        if (id == null || id <= 0L) {
            throw new ServiceException("传入的api信息主键id为空");
        }
        // 查数据是否存在
        WeatherApiInfoDO weatherApiInfoDO = weatherApiInfoDAO.selectById(id);
        if (weatherApiInfoDO == null) {
            throw new ServiceException("未查找到相关api信息");
        }
        weatherApiInfoDAO.deleteById(id);

        // 删除api关联关系
        LambdaQueryWrapper<WeatherApiRequestRelationDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeatherApiRequestRelationDO::getApi_id, id);
        List<WeatherApiRequestRelationDO> requestRelationDOList = weatherApiRequestRelationDAO.selectList(queryWrapper);
        List<Long> idList = requestRelationDOList.stream().map(WeatherApiRequestRelationDO::getId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(idList)) {
            weatherApiRequestRelationDAO.deleteBatchIds(idList);
        }
    }

    @Override
    public void updateApiInfo(WeatherApiInfoVO weatherApiInfoVO) {
        if (weatherApiInfoVO == null) {
            throw new ServiceException("传入参数为空");
        }
        Long id = weatherApiInfoVO.getId();
        if (id == null || id <= 0L) {
            throw new ServiceException("传入的api信息主键id为空");
        }
        WeatherApiInfoDO apiInfoDO = weatherApiInfoDAO.selectById(id);
        if (apiInfoDO == null) {
            throw new ServiceException("未查找到相关api信息");
        }
        List<String> requestTypeList = weatherApiInfoVO.getRequestType();
        String requestTypes = String.join("/", requestTypeList);

        WeatherApiInfoDO weatherApiInfoDO = new WeatherApiInfoDO();
        weatherApiInfoDO.setName(weatherApiInfoVO.getName());
        weatherApiInfoDO.setUrl(weatherApiInfoVO.getUrl());
        weatherApiInfoDO.setRequestType(requestTypes);
        weatherApiInfoDO.setIsFree(weatherApiInfoVO.getIsFree());
        weatherApiInfoDO.setFrequency(weatherApiInfoVO.getFrequency());
        weatherApiInfoDO.setCharge(weatherApiInfoVO.getCharge());
        weatherApiInfoDO.setApiKey(weatherApiInfoVO.getApiKey());
        weatherApiInfoDO.setApiType(weatherApiInfoVO.getApiType());
        weatherApiInfoDO.setId(weatherApiInfoVO.getId());

        weatherApiInfoDAO.updateById(weatherApiInfoDO);

    }

    @Override
    public WeatherApiInfoDTO selectApiById(Long id) {
        if (id == null || id <= 0L) {
            throw new ServiceException("传入的api信息主键id为空");
        }
        WeatherApiInfoDO weatherApiInfoDO = weatherApiInfoDAO.selectById(id);

        return BeanUtils.copyToObject(weatherApiInfoDO, WeatherApiInfoDTO.class);
    }

    @Override
    public PageData<WeatherApiInfoVO> pageQueryByApi(WeatherApiInfoPageQueryParamVO weatherApiInfoPageQueryParamVO) {
        if (weatherApiInfoPageQueryParamVO == null) {
            weatherApiInfoPageQueryParamVO = new WeatherApiInfoPageQueryParamVO();
            weatherApiInfoPageQueryParamVO.setPageNo(GenericConstants.DEFAULT_PAGE_NO);
            weatherApiInfoPageQueryParamVO.setPageSize(GenericConstants.DEFAULT_PAGE_SIZE);
        }
        QueryWrapper<WeatherApiInfoDO> queryWrapper = QueryWrapperUtils.getQueryWrapper(weatherApiInfoPageQueryParamVO);
        queryWrapper.orderByDesc("id");

        Page<WeatherApiInfoDO> page = Page.of(weatherApiInfoPageQueryParamVO.getPageNo(), weatherApiInfoPageQueryParamVO.getPageSize());

        PageData<WeatherApiInfoDO> pageData = PageUtils.getPageData(weatherApiInfoDAO.selectPage(page, queryWrapper), weatherApiInfoPageQueryParamVO);
        if (CollUtil.isEmpty(pageData.getData())) {
            return new PageData<>();
        }

        return pageData.transformData(WeatherApiInfoVO.class);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRequestParamInfo(RequestParamInfoVO requestParamInfoVO) {
        if (requestParamInfoVO == null) {
            throw new ServiceException("传入的请求参数信息为空");
        }
        // 校验code是否重复
        String code = requestParamInfoVO.getCode();
        if (StringUtils.isBlank(code)) {
            throw new ServiceException("未传入参量名称");
        }
        LambdaQueryWrapper<WeatherRequestDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeatherRequestDO::getCode, code);
        Long codeNumber = weatherRequestDAO.selectCount(queryWrapper);
        if (codeNumber > 0L) {
            throw new ServiceException("参数名称已存在");
        }
        // 新增请求参数
        WeatherRequestDO weatherRequestDO = new WeatherRequestDO();
        weatherRequestDO.setCode(requestParamInfoVO.getCode());
        weatherRequestDO.setName(requestParamInfoVO.getName());
        weatherRequestDO.setDescription(requestParamInfoVO.getDescription());
        weatherRequestDO.setRequired(requestParamInfoVO.getRequired());
        weatherRequestDO.setDefaultValue(requestParamInfoVO.getDefaultValue());

        weatherRequestDAO.insert(weatherRequestDO);

        // 新增关联关系
        Long apiId = requestParamInfoVO.getApiId();
        if (apiId == null || apiId <= 0L) {
            throw new ServiceException("未传入api信息主键id");
        }
        WeatherApiRequestRelationDO weatherApiRequestRelationDO = new WeatherApiRequestRelationDO();
        weatherApiRequestRelationDO.setApi_id(apiId);
        weatherApiRequestRelationDO.setRequest_id(weatherRequestDO.getId());

        weatherApiRequestRelationDAO.insert(weatherApiRequestRelationDO);

    }

    @Override
    public WeatherRequestDTO selectRequestInfoById(Long id) {
        if (id == null || id <= 0L) {
            throw new ServiceException("未传入请求参数id");
        }
        WeatherRequestDO weatherRequestDO = weatherRequestDAO.selectById(id);

        return BeanUtils.copyToObject(weatherRequestDO, WeatherRequestDTO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRequestParamInfo(Long id) {
        if (id == null || id <= 0L) {
            throw new ServiceException("未传入请求参数id");
        }
        // 删之前查询是否存在
        WeatherRequestDO weatherRequestDO = weatherRequestDAO.selectById(id);
        if (weatherRequestDO == null) {
            throw new ServiceException("未查找到对应的请求参数信息");
        }

        weatherRequestDAO.deleteById(id);

        // 删除关联关系
        LambdaQueryWrapper<WeatherApiRequestRelationDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeatherApiRequestRelationDO::getRequest_id, id);
        List<WeatherApiRequestRelationDO> requestRelationDOList = weatherApiRequestRelationDAO.selectList(queryWrapper);
        List<Long> idList = requestRelationDOList.stream().map(WeatherApiRequestRelationDO::getId).collect(Collectors.toList());
        // 有关联关系就删
        if (CollUtil.isNotEmpty(idList)) {
            weatherApiRequestRelationDAO.deleteBatchIds(idList);
        }

    }

    @Override
    public void updateRequestParamInfo(RequestParamInfoVO requestParamInfoVO) {
        if (requestParamInfoVO == null) {
            throw new ServiceException("传入的请求参数信息为空");
        }
        Long id = requestParamInfoVO.getId();
        if (id == null || id <= 0L) {
            throw new ServiceException("传入的请求参数信息主键id为空");
        }
        String code = requestParamInfoVO.getCode();
        LambdaQueryWrapper<WeatherRequestDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeatherRequestDO::getCode, code);
        queryWrapper.ne(WeatherRequestDO::getId, id);
        Long countByResponse = weatherRequestDAO.selectCount(queryWrapper);
        if (countByResponse > 0L) {
            throw new ServiceException("参数名称已存在");
        }
        WeatherRequestDO requestDO = weatherRequestDAO.selectById(id);
        if (requestDO == null) {
            throw new ServiceException("未查找到对应请求参数信息");
        }
        WeatherRequestDO weatherRequestDO = new WeatherRequestDO();
        weatherRequestDO.setId(requestParamInfoVO.getId());
        weatherRequestDO.setCode(code);
        weatherRequestDO.setName(requestParamInfoVO.getName());
        weatherRequestDO.setDescription(requestParamInfoVO.getDescription());
        weatherRequestDO.setRequired(requestParamInfoVO.getRequired());
        weatherRequestDO.setDefaultValue(requestParamInfoVO.getDefaultValue());

        weatherRequestDAO.updateById(weatherRequestDO);
    }

    @Override
    public PageData<RequestParamInfoVO> pageQueryByRequestParam(PageParam pageParam) {
        if (pageParam == null) {
            pageParam = new PageParam();
            pageParam.setPageNo(GenericConstants.DEFAULT_PAGE_NO);
            pageParam.setPageSize(GenericConstants.DEFAULT_PAGE_SIZE);
        }
        IPage<WeatherRequestDO> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
        IPage<WeatherRequestDO> pageInfo = weatherRequestDAO.selectPage(page, null);

        PageData<WeatherRequestDO> pageData = new PageData<>();
        pageData.setTotalPage(pageInfo.getPages());
        pageData.setTotalCount(pageInfo.getTotal());
        pageData.setData(pageInfo.getRecords());

        return pageData.transformData(RequestParamInfoVO.class);
    }

    @Override
    public List<RequestParamInfoVO> selectRequestByApiId(Long apiId) {
        if (apiId == null || apiId <= 0L) {
            throw new ServiceException("传入的api接口信息主键id为空");
        }
        List<WeatherRequestDTO> weatherRequestDTOS = weatherRequestDAO.selectRequestInfoByApiId(apiId);
        if (CollUtil.isEmpty(weatherRequestDTOS) || weatherRequestDTOS.size() == 0) {
            return new ArrayList<>();
        }

        return BeanUtils.copyToList(weatherRequestDTOS, RequestParamInfoVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveResponseParamInfo(ResponseParamInfoVO responseParamInfoVO) {
        if (responseParamInfoVO == null) {
            throw new ServiceException("传入的返回参数信息为空");
        }
        // 校重
        String code = responseParamInfoVO.getCode();
        LambdaQueryWrapper<WeatherResponseDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeatherResponseDO::getCode, code);
        Long codeNumber = weatherResponseDAO.selectCount(queryWrapper);
        if (codeNumber > 0L) {
            throw new ServiceException("参数名称已存在");
        }
        // 新增返回参数
        WeatherResponseDO weatherResponseDO = new WeatherResponseDO();
        weatherResponseDO.setCode(responseParamInfoVO.getCode());
        weatherResponseDO.setName(responseParamInfoVO.getName());
        weatherResponseDO.setDescription(responseParamInfoVO.getDescription());

        weatherResponseDAO.insert(weatherResponseDO);

        // 新增关联关系
        Long apiId = responseParamInfoVO.getApiId();
        if (apiId == null || apiId <= 0L) {
            throw new ServiceException("未传入api信息主键id");
        }
        WeatherApiResponseRelationDO weatherApiResponseRelationDO = new WeatherApiResponseRelationDO();
        weatherApiResponseRelationDO.setApi_id(apiId);
        weatherApiResponseRelationDO.setResponse_id(weatherResponseDO.getId());

        weatherApiResponseRelationDAO.insert(weatherApiResponseRelationDO);

    }

    @Override
    public WeatherResponseDTO selectResponseInfoById(Long id) {
        if (id == null || id <= 0L) {
            throw new ServiceException("未传入返回参数id");
        }
        WeatherResponseDO weatherResponseDO = weatherResponseDAO.selectById(id);

        return BeanUtils.copyToObject(weatherResponseDO, WeatherResponseDTO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteResponseParamInfo(Long id) {
        if (id == null || id <= 0L) {
            throw new ServiceException("未传入返回参数id");
        }
        // 删之前查询是否存在
        WeatherResponseDO weatherResponseDO = weatherResponseDAO.selectById(id);
        if (weatherResponseDO == null) {
            throw new ServiceException("未查找到对应的返回参数信息");
        }

        weatherResponseDAO.deleteById(id);

        // 删除关联关系
        LambdaQueryWrapper<WeatherApiResponseRelationDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeatherApiResponseRelationDO::getResponse_id, id);
        List<WeatherApiResponseRelationDO> responseRelationDOList = weatherApiResponseRelationDAO.selectList(queryWrapper);
        List<Long> idList = responseRelationDOList.stream().map(WeatherApiResponseRelationDO::getId).collect(Collectors.toList());
        // 有关联关系就删
        if (CollUtil.isNotEmpty(idList)) {
            weatherApiResponseRelationDAO.deleteBatchIds(idList);
        }

    }

    @Override
    public void updateResponseParamInfo(ResponseParamInfoVO responseParamInfoVO) {
        if (responseParamInfoVO == null) {
            throw new ServiceException("传入的返回参数信息为空");
        }
        Long id = responseParamInfoVO.getId();
        if (id == null || id <= 0L) {
            throw new ServiceException("传入的返回参数信息主键id为空");
        }
        String code = responseParamInfoVO.getCode();
        LambdaQueryWrapper<WeatherResponseDO> responseDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        responseDOLambdaQueryWrapper.eq(WeatherResponseDO::getCode, code);
        responseDOLambdaQueryWrapper.ne(WeatherResponseDO::getId, id);
        Long countByResponse = weatherResponseDAO.selectCount(responseDOLambdaQueryWrapper);
        if (countByResponse > 0L) {
            throw new ServiceException("参数名称已存在");
        }
        WeatherResponseDO responseDO = weatherResponseDAO.selectById(id);
        if (responseDO == null) {
            throw new ServiceException("未查找到对应返回参数信息");
        }
        WeatherResponseDO weatherResponseDO = new WeatherResponseDO();
        weatherResponseDO.setId(responseParamInfoVO.getId());
        weatherResponseDO.setCode(code);
        weatherResponseDO.setName(responseParamInfoVO.getName());
        weatherResponseDO.setDescription(responseParamInfoVO.getDescription());

        weatherResponseDAO.updateById(weatherResponseDO);
    }

    @Override
    public PageData<ResponseParamInfoVO> pageQueryByResponseParam(PageParam pageParam) {
        if (pageParam == null) {
            pageParam = new PageParam();
            pageParam.setPageNo(GenericConstants.DEFAULT_PAGE_NO);
            pageParam.setPageSize(GenericConstants.DEFAULT_PAGE_SIZE);
        }
        IPage<WeatherResponseDO> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
        IPage<WeatherResponseDO> pageInfo = weatherResponseDAO.selectPage(page, null);

        PageData<WeatherResponseDO> pageData = new PageData<>();
        pageData.setTotalPage(pageInfo.getPages());
        pageData.setTotalCount(pageInfo.getTotal());
        pageData.setData(pageInfo.getRecords());

        return pageData.transformData(ResponseParamInfoVO.class);
    }

    @Override
    public List<ResponseParamInfoVO> selectResponseByApiId(Long apiId) {
        if (apiId == null || apiId <= 0L) {
            throw new ServiceException("传入的api接口信息主键id为空");
        }
        List<WeatherResponseDTO> weatherResponseDTOS = weatherResponseDAO.selectResponseInfoByApiId(apiId);
        if (CollUtil.isEmpty(weatherResponseDTOS) || weatherResponseDTOS.size() == 0) {
            return new ArrayList<>();
        }

        return BeanUtils.copyToList(weatherResponseDTOS, ResponseParamInfoVO.class);
    }

    public static void main(String[] args) {
        List<String> requestTypeList = Arrays.asList("GET", "POST");
        String join = String.join("/", requestTypeList);
        WeatherApiInfoDO weatherApiInfoDO = new WeatherApiInfoDO();
        weatherApiInfoDO.setRequestType(join);
        System.out.println("之前" + weatherApiInfoDO);
        System.out.println("之后" + BeanUtils.copyToObject(weatherApiInfoDO, WeatherApiInfoVO.class));

    }
}
